package com.ayitubie.refuelweb.minio;

import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;


@Slf4j
@NoArgsConstructor
@Component
@Configuration
public class MinioTemplate {
    private static String URL;
    private static String ACCESSKEY;
    private static String SECRETKEY;
    private static String BCUKETNAME;
    private static int EXPIRES = 7;

    @Value("${minio.url}")
    public void initUrl(String s) {
        URL = s;
    }

    @Value("${minio.access-key}")
    public void initAccessKey(String ak) {
        ACCESSKEY = ak;
    }

    @Value("${minio.secret-key}")
    public void initSecretKey(String sk) {
        SECRETKEY = sk;
    }

    @Value("${minio.bucket-name}")
    public void initBucketName(String bn) {
        BCUKETNAME = bn;
    }

    private MinioClient minioClient;

    public MinioClient getMinioClient() {
        System.out.println("URL" + ":" + URL);
        System.out.println("ACCESSKEY" + ":" + ACCESSKEY);
        System.out.println("SECRETKEY" + ":" + SECRETKEY);
        if (minioClient == null) {
            try {
                minioClient =
                        MinioClient.builder()
                                .endpoint(URL)
                                .credentials(ACCESSKEY, SECRETKEY)
                                .build();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return minioClient;
    }

    public String getObjectURL(String bucketName, String objectName, int expires) {
        if (StringUtils.isBlank(bucketName)) {
            bucketName = BCUKETNAME;
        }
        if (expires == 0) {
            expires = EXPIRES;
        }
        String url =
                null;
        try {
            url = getMinioClient().getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(Method.GET)
                            .bucket(bucketName)
                            .object(objectName)
                            .expiry(expires, TimeUnit.DAYS)
                            .build());
        } catch (Exception e) {
            log.info("Minio getObjectUrl Error [{}]", e.getMessage());
        }
        return url;
    }


    public String uploadFile(InputStream inputStream, String bucketname, String objectname, String contentType) throws Exception {
        String filePath = null;
        try {
            getMinioClient().putObject(
                    PutObjectArgs.builder().bucket(bucketname).object(objectname).stream(
                            inputStream, -1, 10485760)
                            .contentType(contentType)
                            .build());
            filePath = objectname;
        } catch (ErrorResponseException e) {
            log.info("上传文件失败 [{}]", e);
        }
        return filePath;
    }

    public InputStream downloadFile(String bucketName, String filename) throws Exception {
        return getMinioClient().getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(filename)
                .build());
    }

    public void mergeChunks(String fileName, int totalChunks,String bucketName,String contentType) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            for (int i = 0; i < totalChunks; i++) {
                String objectName = "/chunk/" + fileName + "_" + i;
                InputStream inputStream = getMinioClient().getObject(
                        GetObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .build()
                );
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                inputStream.close();
            }

            byte[] mergedFile = outputStream.toByteArray();
        
            getMinioClient().putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .contentType(contentType)
                            .object(fileName)
                            .stream(new ByteArrayInputStream(mergedFile), mergedFile.length, -1)
                            .build()
            );
        }catch(Exception e){
            throw new IOException("合并分片失败", e);
        }
    }

}
